﻿using System;
using System.Collections.Generic;
using EnvDTE;
using EnvDTE80;
using Microsoft.VisualStudio.CommandBars;


namespace VsTortoiseSVN.Commands
{
    public class CommandManager
    {
        private Dictionary<string, CommandBase> _commands = new Dictionary<string, CommandBase>();
        private Dictionary<string, Command> _commandsGuids = new Dictionary<string, Command>();
        private DTE2 _dte;
        private AddIn _addIn;
        
        /// <summary>
        /// Constructor
        /// </summary>
        public CommandManager(DTE2 app, AddIn addin)
        {
            _dte = app;
            _addIn = addin;
        }

        /// <summary>
        /// Adds a command to the manager.
        /// </summary>
        /// <param name="command">Reference to the command to add</param>
        public void Add(CommandBase command)
        {
            Commands2 vsCommands = (Commands2)_dte.Commands;

            // Get full name how Visual Studio queries this command
            string fullname = vsCommands.GetFullname(_addIn, command.Name);

            // Create the command inside Visual Studio permanently
            Command vsCommand = vsCommands.CreateCommandButton(_addIn, command);
            if (null != vsCommand)
            {
                // Add to our own VsTortoise command management
                _commands[fullname] = command;

                if (!_commandsGuids.ContainsKey(vsCommand.Guid))
                    _commandsGuids.Add(vsCommand.Guid, vsCommand);
            }
        }

        /// <summary>
        /// Gets status of the command with the specified fullname.
        /// Whenever a command button is about to appear, Visual Studio queries its status.
        /// </summary>
        public vsCommandStatus QueryStatus(string fullname)
        {
            if (Exists(fullname))
                return _commands[fullname].QueryStatus();

            return vsCommandStatus.vsCommandStatusUnsupported;
        }

        /// <summary>
        /// Executes the command with the specified fullname.
        /// </summary>
        public bool Exec(string fullname)
        {
            if (Exists(fullname))
            {
                CommandBase command = _commands[fullname];
                if (command.SaveRequired)
                {
                    if (!_dte.SaveDocuments())
                        return false;
                }

                return command.Exec();
            }

            return false;
        }

        /// <summary>
        /// Checks whether the command with the specified fullname exists.
        /// </summary>
        public bool Exists(string fullname)
        {
            return _commands.ContainsKey(fullname);
        }

        public void DeleteStandardVsTortoiseUI()
        {
            foreach (CommandBar cmdBar in (CommandBars)_dte.CommandBars)
            {
                if (cmdBar == null || cmdBar.Type != MsoBarType.msoBarTypePopup)
                    continue; // VsTortoise adds standard button to popups only

                // cmdBar.Controls items are in range "1..cmdBar.Controls.Count" NOT "0..cmdBar.Controls.Count-1" !!!
                for (var n = cmdBar.Controls.Count; n >= 1; --n)
                {
                    // get the associated command of this control
                    var ctrl = cmdBar.Controls[n];
                    var vsCommand = ctrl.GetCommand();
                    if (null != vsCommand)
                    {
                        // if this command belongs to VsTortoise, delete the control
                        if (_commandsGuids.ContainsKey(vsCommand.Guid))
                            ctrl.Delete(Type.Missing);
                    }
                }
            }
        }
    }
}
